home *** CD-ROM | disk | FTP | other *** search
- /* ClockView.m, a simple clock view
- * Author: Ali T. Ozer, NeXT Developer Support Group
- * Created: May 26, 1989 (for version 0.9)
- * Modified: June 14 and Aug 14, 1989 (for version 1.0)
- * Redesigned for 2.0 by Julie Zelenski, NeXT Developer Support Group
- * Adapted by Mai Nguyen for this mini-example. Basically, only the digital
- * view of the clock is being used.
- *
- * Subclass of view to implement a simple clock. This view is pretty generic
- * and can probably be added to any program.
- * You may freely copy, distribute and reuse the code in this example.
- * NeXT disclaims any warranty of any kind, expressed or implied, as to its
- * fitness for any particular use.
- */
-
- #import "ClockView.h"
- #import "Clock.h" // PSwrap routines
- #import <appkit/Application.h>
- #import <appkit/Button.h>
- #import <appkit/Window.h>
- #import <appkit/Font.h>
- #import <objc/NXStringTable.h>
- #import <string.h>
- #import <sys/time.h>
- #import <dpsclient/wraps.h>
- #import <appkit/nextstd.h>
-
- @implementation ClockView:View
-
-
- /* ShowTime() is the timed entry function called by the
- * timed entry mechanism. It first writes the time out on the face
- * of the clock, and then reinstalls the timed entry if the clock is
- * not showing the seconds. If the seconds are being shown, no need to
- * reinstall the timed entry; a second skipped here and then won't matter.
- * If minutes are being shown, we want to make sure that the minute jumps
- * at the next top of the minute, regardless of how long it took to service
- * the timed entry.
- */
- void ShowTime (teNum, now, clock)
- DPSTimedEntry teNum;
- double now;
- id clock;
- {
- [clock display];
- [[clock stopTimedEntry] startTimedEntry:NO];
-
- }
-
-
-
-
- - initFrame:(const NXRect *)frameRect
- /* initFrame for newly created view, initializes the various paramaters.
- * The constants above determine the lengths of the clock hands.
- */
- {
- [super initFrame:frameRect];
- cacheWindow = [Window newContent:frameRect
- style:NX_PLAINSTYLE
- backing:NX_RETAINED
- buttonMask:0
- defer:NO];
- littleFont = [Font newFont:"Helvetica" size:12 style:0
- matrix:NX_IDENTITYMATRIX];
- mediumFont = [Font newFont:"Times-Roman" size:14 style:0
- matrix:NX_IDENTITYMATRIX];
- bigFont = [Font newFont:"Times-Roman" size:24 style:0
- matrix:NX_IDENTITYMATRIX];
-
- /* Set the default state (NO seconds, no date) */
-
- showSeconds = NO;
- center.x = bounds.size.width/2.0;
- center.y = bounds.size.height/2.0 + [mediumFont pointSize]/2.0;
- radius = MIN(center.x,center.y-[mediumFont pointSize]);
- needRedraw = YES;
-
- /* Start the time entry. YES indicates that this is the first time */
- [self startTimedEntry:YES];
- [self display];
- return self;
- }
-
-
- - free
- /* Good idea to get rid of the timed entry while freeing...
- */
- {
- [cacheWindow free];
- [self stopTimedEntry];
- return [super free];
- }
-
-
-
-
- /* PRIVATE METHODS */
-
- - drawFace;
- /* drawFace draws the clock face image in the offscreen window. This
- * offscreen cache is composited on screen and then the hands, shadow,
- * whatever is drawn on top of the face for the current time. Just
- * erase the background before redrawing the digital time.
- */
- {
-
- [[cacheWindow contentView] lockFocus];
-
- PSsetgray (NX_LTGRAY);
- NXRectFill (&bounds); // Erase background
- [[cacheWindow contentView] unlockFocus];
- needRedraw = NO;
- return self;
- }
-
- - drawDigital:(struct tm *)time;
- /* drawDigital draws the time and date for the digital clock face
- */
- {
- int hour;
- char timeString[10];
-
-
- hour = fmod(time->tm_hour,12); /* get us off military time */
- if (!hour) hour = 12; /* if noon or midnight */
- if (showSeconds)
- sprintf(timeString,"%d:%.2d:%.2d",hour,
- time->tm_min,
- time->tm_sec);
- else
- sprintf(timeString,"%d:%.2d", hour,time->tm_min);
- [mediumFont set];
- PSWcenterShow(center.x,center.y-8.0,timeString,NX_BLACK);
- return self;
- }
-
-
-
-
- - drawSelf:(NXRect *)rects :(int)rectCount
- /* Draws face and hands of clock. If needRedraw is YES, a parameter has
- * changed and the face must be redrawn in the offscreen window.
- * Otherwise, the image in cacheWindow is copied into the bounds of the
- * view, and a routine is called to display the current date and time
- */
- {
- struct tm *localTime;
- struct timeval currentTime;
-
- if (needRedraw) [self drawFace];
- PScomposite(0.0, 0.0, bounds.size.width, bounds.size.height,
- [cacheWindow gState], bounds.origin.x, bounds.origin.y,
- NX_COPY);
-
- gettimeofday (¤tTime, NULL);
- localTime = localtime (&(currentTime.tv_sec));
- [self drawDigital:localTime];
- return self;
- }
-
-
- - startTimedEntry:(BOOL)fireASAP
- /* startTimedEntry will install the timed entry. If fireASAP is YES, the
- * timed entry is set to fire off as soon as possible (this would be the case
- * at the start of the program, for instance). If fireASAP is NO, then the
- * timed entry is set to fire off in one second (if seconds are being shown)
- * or at the top of the next minute (in anytime between 0 and 60 seconds).
- */
- {
- double fireIn;
-
- if (fireASAP) fireIn = 0.0; // Fire as soon as possible!
- else if (showSeconds) fireIn = 1.0; // Fire in a second (good enough)
- else {
- struct timeval currentTime;
- gettimeofday (¤tTime, NULL);
- fireIn = 60.0 - (currentTime.tv_sec % 60); // Top of the minute
- }
-
- teNum = DPSAddTimedEntry(fireIn, &ShowTime, self, NX_MODALRESPTHRESHOLD);
- return self;
- }
-
- - stopTimedEntry
- /* Removes the clock timed entry.
- */
- {
- if (teNum)
- DPSRemoveTimedEntry (teNum);
- teNum = (DPSTimedEntry)0;
- return self;
- }
-
-
- - sizeTo:(NXCoord)w :(NXCoord)h
- /* Overriding sizeTo:: allows us to resize and fix up the clock whenever
- * the size is changed. Figure the radius of the clock (based on the size
- * of the view) and then redraw
- */
- {
- [super sizeTo:w :h];
- center.x = bounds.size.width/2.0;
- center.y = bounds.size.height/2.0 + [mediumFont pointSize]/2.0;
- radius = MIN(center.x, center.y-[mediumFont pointSize]);
- needRedraw = YES;
- return self;
- }
-
-
-
- @end